package Factory;

import java.util.ArrayList;
import java.util.Random;

import tree.Node;
import tree.TreeNodesManager;
import tree.nodeType.numeric.functions.Div;
import tree.nodeType.numeric.functions.ExponentialMovingAverage;
import tree.nodeType.numeric.functions.Maximum;
import tree.nodeType.numeric.functions.Minimum;
import tree.nodeType.numeric.functions.Minus;
import tree.nodeType.numeric.functions.MovingAverage;
import tree.nodeType.numeric.functions.Multi;
import tree.nodeType.numeric.functions.Plus;
import tree.nodeType.numeric.functions.Power;
import tree.nodeType.numeric.functions.Sinus;
/**
 * factory of numeric nodes (Exponential Avg,Moving Avg,Maximum,Minimum)
 *
 */
public class NumericNodesFactory{
	private Random random;
	private ArrayList<Factory>numericNodesFactories;
	
	private class MovingAVGFactory implements Factory{

		@Override
		public Node createNode(Node parent, int depth, int maxDepth,TreeNodesManager treeNodesManager) {
			
			return new MovingAverage(parent, depth,maxDepth,treeNodesManager);
		}
		
	}
	
	private class MinFactory implements Factory{
		@Override
		public Node createNode(Node parent, int depth, int maxDepth,TreeNodesManager treeNodesManager) {
			
			return new Minimum(parent, depth,maxDepth,treeNodesManager);
		}
		
	}
	
	private class MaxFactory implements Factory{
		@Override
		public Node createNode(Node parent, int depth, int maxDepth,TreeNodesManager treeNodesManager) {
			
			return new Maximum(parent, depth, maxDepth,treeNodesManager);
		}
		
	}
	
	private class ExpMovingAVGFactory implements Factory{
		@Override
		public Node createNode(Node parent, int depth, int maxDepth,TreeNodesManager treeNodesManager) {
			
			return new ExponentialMovingAverage(parent, depth, maxDepth,treeNodesManager);

		}
	}
	private class MinusFactory implements Factory{
		@Override
		public Node createNode(Node parent, int depth, int maxDepth,TreeNodesManager treeNodesManager) {
			if (depth<maxDepth){
				return new Minus(parent, depth, maxDepth,treeNodesManager);
			}else{
				return null;
			}

		}
	}
	private class PlusFactory implements Factory{
		@Override
		public Node createNode(Node parent, int depth, int maxDepth,TreeNodesManager treeNodesManager) {
			if (depth<maxDepth){
				return new Plus(parent, depth, maxDepth,treeNodesManager);
			}else{
				return null;
			}
		}
	}
	private class MultiFactory implements Factory{
		@Override
		public Node createNode(Node parent, int depth, int maxDepth,TreeNodesManager treeNodesManager) {
			if (depth<maxDepth){
				return new Multi(parent, depth, maxDepth,treeNodesManager);
			}else{
				return null;
			}
		}
	}
	private class DivFactory implements Factory{
		@Override
		public Node createNode(Node parent, int depth, int maxDepth,TreeNodesManager treeNodesManager) {
			if (depth<maxDepth){
				return new Div(parent, depth, maxDepth,treeNodesManager);
			}else{
				return null;
			}

		}
	}
	private class PowerFactory implements Factory{
		@Override
		public Node createNode(Node parent, int depth, int maxDepth,TreeNodesManager treeNodesManager) {
			if (depth<maxDepth){
				return new Power(parent, depth, maxDepth,treeNodesManager);
			}else{
				return null;
			}

		}
	}
	private class SinusFactory implements Factory{
		@Override
		public Node createNode(Node parent, int depth, int maxDepth,TreeNodesManager treeNodesManager) {
			if (depth<maxDepth){
				return new Sinus(parent, depth, maxDepth,treeNodesManager);
			}else{
				return null;
			}

		}
	}
	

	public NumericNodesFactory() {
		random=new Random();
		numericNodesFactories=new ArrayList<Factory>();
		numericNodesFactories.add(new MovingAVGFactory());
		numericNodesFactories.add(new MinFactory());
		numericNodesFactories.add(new MaxFactory());
		numericNodesFactories.add(new ExpMovingAVGFactory());
		numericNodesFactories.add(new MinusFactory());
		numericNodesFactories.add(new PlusFactory());
		numericNodesFactories.add(new MultiFactory());
		//numericNodesFactories.add(new DivFactory());
		//numericNodesFactories.add(new PowerFactory());
		numericNodesFactories.add(new SinusFactory());
	}

	public Node createRandomNode(Node parent, int depth, int maxDepth,TreeNodesManager treeNodesManager){
		Node newNode=null;;
		do {
			newNode=numericNodesFactories.get(random.nextInt(numericNodesFactories.size()))
			.createNode(parent, depth, maxDepth,treeNodesManager);
		}while (newNode==null);
		return newNode;
	}
	
}


